#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <syslog.h>
#include <signal.h>
#include <unistd.h>
#include <glib.h>
#include "Helper.h"
#include "define.h"
#include <sstream>

using namespace std;

int test_set(int iargc)
{ //method + hash + expire + argc + k-v.k-v
	Helper *p = Helper::Instance();
	if( p == NULL)
	{
		cerr<<"helper Instance == NULL"<< endl;
		return 1;
	}
	char buf[1024];
	int imethod = 1;
	int usedlen = 0;
        cout<<"offset = "<< usedlen << "; imethod = "<< imethod << endl;
	bcopy(&imethod, buf + usedlen, 4);   
	usedlen += 4;       
 
        int ihash = 10;
        cout<<"offset = "<< usedlen << "; ihash = "<< ihash << endl;
	bcopy(&ihash, buf + usedlen, 4);
	usedlen += 4;

        long expire =10099;
        cout<<"offset = "<< usedlen << "; expire = "<< expire << endl;
	bcopy(&expire, buf + usedlen, sizeof(long));  
	usedlen += sizeof(long);   

        cout<< "sizeof(long) = "<< sizeof(long) << endl;
	cout<<"offset = "<< usedlen << "; iargc = "<< iargc << endl;
	bcopy(&iargc, buf + usedlen, 4);  
	usedlen += 4;   

	for(int i=0; i< iargc; i++)
	{
		ostringstream k, v;
		k << "name-" << i;
		v << "0"<<i;
		int ik = k.str().length();
		int iv = v.str().length();

		bcopy(&ik, buf + usedlen, 4);
		usedlen += 4;
		bcopy( &k.str().at(0), buf + usedlen, ik);       // val
		usedlen += ik;

		bcopy(&iv, buf + usedlen, 4);
		usedlen += 4;
		bcopy( &v.str().at(0), buf + usedlen, iv);       // val
		usedlen += iv;  
        }
 
	char *retBuf = NULL;
	unsigned int retBlen = 0;
	int ret = p->Do_Method(imethod, buf + 4, usedlen-4, &retBuf, retBlen );
	if(retBuf !=NULL)
	{
		cout<<retBuf<<endl;
		free(retBuf);
	}
        return ret;
}

int test_get(int kc )
{ //method + hash + expire + argc + k-v.k-v
	Helper *p = Helper::Instance();
	if( p == NULL)
	{
		cerr<<"helper Instance == NULL"<< endl;
		return 1;
	}
	char buf[1024];
	int imethod = 2;
	int usedlen = 0;
        cout<<"offset = "<< usedlen << "; imethod = "<< imethod << endl;
	bcopy(&imethod, buf + usedlen, 4);   
	usedlen += 4;       
 
        int ihash = 10;
        cout<<"offset = "<< usedlen << "; ihash = "<< ihash << endl;
	bcopy(&ihash, buf + usedlen, 4);
	usedlen += 4;
 
        cout<<"offset = "<< usedlen << "; keycounts = "<<  kc << endl;
	bcopy(&kc, buf + usedlen, 4);
	usedlen += 4;
    
	for(int i=0; i< kc; i++)
	{
		ostringstream k;
		k << "name-" << i;
		int klen = k.str().length();
		bcopy(&klen, buf + usedlen, 4);
		usedlen += 4;
		bcopy(k.str().c_str(), buf + usedlen, klen);       // val
		usedlen += klen;
	}
	char *retBuf = NULL;
	unsigned int retBlen = 0;
	int ret = p->Do_Method(imethod, buf + 4, usedlen-4, &retBuf, retBlen );
        if(ret == 0 )
        {
		unsigned ilen = 0;
		unsigned revlen  = 0;
		bcopy(retBuf,  &revlen, 4);
		ilen +=  4;
                int iret = 0;
		bcopy(retBuf + ilen ,  &iret, 4);
		ilen +=  4;
 
                int icount = 0;
		bcopy(retBuf + ilen ,  &icount, 4);
		ilen +=  4;
                
                cout<< retBlen<<" ?revlen = "<< revlen<<"; iret="<<iret<<"; icount="<<icount<<endl;
  
		for(int j=0; j< icount; j++)
		{ 
			int ik, iv;
			bcopy(retBuf + ilen ,  &ik, 4);
			ilen +=  4;
			char *k = g_strndup(retBuf + ilen, ik);
			ilen +=  ik; 

			bcopy(retBuf + ilen ,  &iv, 4);
			ilen +=  4;
			char *v = g_strndup(retBuf + ilen, iv);
			ilen +=  iv; 
			cout<< k <<" = "<< v<<endl;
                        g_free(k);
                        g_free(v);
		}

        }
	if(retBuf !=NULL)
	{
		cout<< retBlen<<":"<<retBuf<<endl;
		free(retBuf);
	}
        return ret;
}


int test_incr(int argc,unsigned int incr )
{ //method + hash +  argc + k-v.k-v
	Helper *p = Helper::Instance();
	if( p == NULL)
	{
		cerr<<"helper Instance == NULL"<< endl;
		return 1;
	}
	char buf[1024];
	int imethod = 3;
	int usedlen = 0;
        cout<<"offset = "<< usedlen << "; imethod = "<< imethod << endl;
	bcopy(&imethod, buf + usedlen, 4);   
	usedlen += 4;       
 
        int ihash = 10;
        cout<<"offset = "<< usedlen << "; ihash = "<< ihash << endl;
	bcopy(&ihash, buf + usedlen, 4);
	usedlen += 4;
 
	ostringstream k;
	k << "name-" << argc;
	int klen = k.str().length();
	bcopy(&klen, buf + usedlen, 4);
	usedlen += 4;
	bcopy(k.str().c_str(), buf + usedlen, klen);       // val
	usedlen += klen;
	bcopy(&incr, buf + usedlen, 4);       // val
	usedlen += 4;

	char *retBuf = NULL;
	unsigned int retBlen = 0;
	int ret = p->Do_Method(imethod, buf + 4, usedlen-4, &retBuf, retBlen );
	if(ret == 0 )
	{
		unsigned ilen = 0;
		unsigned revlen  = 0;
		bcopy(retBuf,  &revlen, 4);
		ilen +=  4;
		int iret = 0;
		bcopy(retBuf + ilen ,  &iret, 4);
		ilen +=  4;
		cout<<"retBlen="<< retBlen<<" ?revlen = "<< revlen<<"; retcode="<<iret << endl;
		if(ilen < retBlen - sizeof(uint64_t))
		{  
			int64_t v;
			bcopy(retBuf + ilen, &v, sizeof(uint64_t));
			ilen +=  sizeof(uint64_t); 
			cout<< k.str().c_str() <<" incr("<<incr << "), result = "<< v<<endl;
		}
	}
        else if(ret == PANDA_MC_NOT_FOUND)
            cout<<"NOT FOUND, YOU SHOULD SET FIRST!"<<endl;

	if(retBuf !=NULL)
	{
		cout<< retBlen<<":"<<retBuf<<endl;
		free(retBuf);
	}
        return ret;
}

int test_decr(int argc, unsigned incr )
{ //method + hash +  argc + k-v.k-v
	Helper *p = Helper::Instance();
	if( p == NULL)
	{
		cerr<<"helper Instance == NULL"<< endl;
		return 1;
	}
	char buf[1024];
	int imethod = 4;
	int usedlen = 0;
        cout<<"offset = "<< usedlen << "; imethod = "<< imethod << endl;
	bcopy(&imethod, buf + usedlen, 4);   
	usedlen += 4;       
 
        int ihash = 10;
        cout<<"offset = "<< usedlen << "; ihash = "<< ihash << endl;
	bcopy(&ihash, buf + usedlen, 4);
	usedlen += 4;
 
	ostringstream k;
	k << "name-" << argc;
	int klen = k.str().length();
	bcopy(&klen, buf + usedlen, 4);
	usedlen += 4;
	bcopy(k.str().c_str(), buf + usedlen, klen);       // val
	usedlen += klen;
	bcopy(&incr, buf + usedlen, 4);       // val
	usedlen += 4;

	char *retBuf = NULL;
	unsigned int retBlen = 0;
	int ret = p->Do_Method(imethod, buf + 4, usedlen-4, &retBuf, retBlen );
        if(ret == 0 )
        {
		unsigned ilen = 0;
		unsigned revlen  = 0;
		bcopy(retBuf,  &revlen, 4);
		ilen +=  4;
                int iret = 0;
		bcopy(retBuf + ilen ,  &iret, 4);
		ilen +=  4;
                cout<<"retBlen="<< retBlen<<" ?revlen = "<< revlen<<"; iret="<<iret << endl;
  
		int64_t v;
                bcopy(retBuf + ilen, &v, sizeof(uint64_t));
		ilen +=  sizeof(uint64_t); 
		cout<< k.str().c_str() <<" decr("<<incr << "), result = "<< v<<endl;
        }
	if(retBuf !=NULL)
	{
		cout<< retBlen<<":"<<retBuf<<endl;
		free(retBuf);
	}
        return ret;
}


int test_delete(int iargc)
{ //method + hash + expire + argc + k-v.k-v
	Helper *p = Helper::Instance();
	if( p == NULL)
	{
		cerr<<"helper Instance == NULL"<< endl;
		return 1;
	}
	char buf[1024];
	int imethod = 5;
	int usedlen = 0;
        cout<<"offset = "<< usedlen << "; imethod = "<< imethod << endl;
	bcopy(&imethod, buf + usedlen, 4);   
	usedlen += 4;       
 
        int ihash = 10;
        cout<<"offset = "<< usedlen << "; ihash = "<< ihash << endl;
	bcopy(&ihash, buf + usedlen, 4);
	usedlen += 4;

	cout<<"offset = "<< usedlen << "; iargc = "<< iargc << endl;
	bcopy(&iargc, buf + usedlen, 4);  
	usedlen += 4;   

	for(int i=0; i< iargc; i++)
	{
		ostringstream k;
		k << "name-" << i;
		int ik = k.str().length();

		bcopy(&ik, buf + usedlen, 4);
		usedlen += 4;
		bcopy( &k.str().at(0), buf + usedlen, ik);       // val
		usedlen += ik;
        }
 
	char *retBuf = NULL;
	unsigned int retBlen = 0;
	int ret = p->Do_Method(imethod, buf + 4, usedlen-4, &retBuf, retBlen );
	if(retBuf !=NULL)
	{
		cout<<retBuf<<endl;
		free(retBuf);
	}
        return ret;
}


int main( int argc, char * argv[] )
{
	string confFile = "../helper.conf";
	Helper *p = Helper::Instance( confFile.c_str());
	if( p == NULL)
	{
		cerr<<"error to init helper :"<< confFile.c_str() <<endl;
		exit(1);
	}
for(int i=0; i<99999999; i++)
{
/*
	test_set(1);
	test_get(1);
	test_incr(0, 10);
	test_get(1);
	test_incr(0, 31);
	test_get(1);
	test_decr(0, 11);
	test_get(1);
*/
/*
      test_set(1);
      test_delete(1);
      test_get(1);
      test_incr(2, 10);
*/

      test_set(2);
      test_get(2);
}

       p->Release(true);
	return 0;
}
